From f66ff602447c200eef76cad55f195ff6c11954aa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Tue, 29 Dec 2015 01:21:50 +0100 Subject: [PATCH] LogEntry: Make associated rev id persistent (store in logging and log_search) The implementation from 0160b410bd514681b1637ccab2b7c79158fbfb29 only stored the associated rev id in the `recentchanges` table, which was sufficient for its purpose of allowing patrol of these log entries and provided some change tagging improvements, but ephemeral. Now we also store it in `logging` and `log_search` tables, which makes it possible to find a revision for the log entry and vice versa. * For `log_search` we just add a row with 'associated_rev_id' as key, it was designed for exactly this purpose. * For `logging` we store it in log_params field in ManualLogEntry, and transparently remove it from there when building a DatabaseLogEntry. Bug: T122089 Change-Id: I559587ff77b3c94b31a6c5951287b6f9c1e167ce --- includes/filerepo/file/LocalFile.php | 35 ++++++++++++++++++++------ includes/logging/LogEntry.php | 37 +++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index 5a6a8b26c0..b7d6f98478 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -1399,6 +1399,7 @@ class LocalFile extends File { # Update memcache after the commit $that->invalidateCache(); + $updateLogPage = false; if ( $newPageContent ) { # New file page; create the description page. # There's already a log entry, so don't make a second RC entry @@ -1420,12 +1421,7 @@ class LocalFile extends File { if ( isset( $status->value['revision'] ) ) { /** @var $rev Revision */ $rev = $status->value['revision']; - $that->getRepo()->getMasterDB()->update( - 'logging', - array( 'log_page' => $rev->getPage() ), - array( 'log_id' => $logId ), - __METHOD__ - ); + $updateLogPage = $rev->getPage(); } } else { # Existing file page: invalidate description page cache @@ -1435,7 +1431,32 @@ class LocalFile extends File { Article::purgePatrolFooterCache( $descId ); } - # Now that the page exists, make an RC entry. + # Update associated rev id. This should be done by $logEntry->insert() earlier, + # but setAssociatedRevId() wasn't called at that point yet... + $logParams = $logEntry->getParameters(); + $logParams['associated_rev_id'] = $logEntry->getAssociatedRevId(); + $update = array( 'log_params' => LogEntryBase::makeParamBlob( $logParams ) ); + if ( $updateLogPage ) { + # Also log page, in case where we just created it above + $update['log_page'] = $updateLogPage; + } + $that->getRepo()->getMasterDB()->update( + 'logging', + $update, + array( 'log_id' => $logId ), + __METHOD__ + ); + $that->getRepo()->getMasterDB()->insert( + 'log_search', + array( + 'ls_field' => 'associated_rev_id', + 'ls_value' => $logEntry->getAssociatedRevId(), + 'ls_log_id' => $logId, + ), + __METHOD__ + ); + + # Now that the log entry is up-to-date, make an RC entry. $logEntry->publish( $logId ); # Run hook for other updates (typically more cache purging) Hooks::run( 'FileUpload', array( $that, $reupload, !$newPageContent ) ); diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php index 773af27d54..db588fd8a7 100644 --- a/includes/logging/LogEntry.php +++ b/includes/logging/LogEntry.php @@ -213,6 +213,12 @@ class DatabaseLogEntry extends LogEntryBase { /** @var User */ protected $performer; + /** @var array Parameters for log entry */ + protected $params; + + /** @var int A rev id associated to the log entry */ + protected $revId = null; + /** @var bool Whether the parameters for this log entry are stored in new or old format. */ protected $legacy; @@ -239,7 +245,7 @@ class DatabaseLogEntry extends LogEntryBase { } public function isLegacy() { - // This does the check + // This extracts the property $this->getParameters(); return $this->legacy; } @@ -265,11 +271,22 @@ class DatabaseLogEntry extends LogEntryBase { $this->params = LogPage::extractParams( $blob ); $this->legacy = true; } + + if ( isset( $this->params['associated_rev_id'] ) ) { + $this->revId = $this->params['associated_rev_id']; + unset( $this->params['associated_rev_id'] ); + } } return $this->params; } + public function getAssociatedRevId() { + // This extracts the property + $this->getParameters(); + return $this->revId; + } + public function getPerformer() { if ( !$this->performer ) { $userId = (int)$this->row->log_user; @@ -321,6 +338,10 @@ class RCDatabaseLogEntry extends DatabaseLogEntry { return $this->row->rc_params; } + public function getAssociatedRevId() { + return $this->row->rc_this_oldid; + } + public function getType() { return $this->row->rc_log_type; } @@ -551,6 +572,16 @@ class ManualLogEntry extends LogEntryBase { // Truncate for whole multibyte characters. $comment = $wgContLang->truncate( $comment, 255 ); + $params = $this->getParameters(); + $relations = $this->relations; + + // Additional fields for which there's no space in the database table schema + $revId = $this->getAssociatedRevId(); + if ( $revId ) { + $params['associated_rev_id'] = $revId; + $relations['associated_rev_id'] = $revId; + } + $data = array( 'log_id' => $id, 'log_type' => $this->getType(), @@ -562,7 +593,7 @@ class ManualLogEntry extends LogEntryBase { 'log_title' => $this->getTarget()->getDBkey(), 'log_page' => $this->getTarget()->getArticleID(), 'log_comment' => $comment, - 'log_params' => LogEntryBase::makeParamBlob( $this->getParameters() ), + 'log_params' => LogEntryBase::makeParamBlob( $params ), ); if ( isset( $this->deleted ) ) { $data['log_deleted'] = $this->deleted; @@ -572,7 +603,7 @@ class ManualLogEntry extends LogEntryBase { $this->id = !is_null( $id ) ? $id : $dbw->insertId(); $rows = array(); - foreach ( $this->relations as $tag => $values ) { + foreach ( $relations as $tag => $values ) { if ( !strlen( $tag ) ) { throw new MWException( "Got empty log search tag." ); } -- 2.20.1